package fem2.gui;

import fem2.Model;
import fem2.gui.pm.HofemPipelineFactory;
import fem2.gui.pm.LinePlotPipeline;
import inf.swing.IntTextField;
import inf.vtk.pm.PipelineCollection;
import inf.vtk.pm.SolidElementsPipeline;
import inf.vtk.pm.uiswing.LeftBox;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

class SettingsPanel extends LeftBox implements PropertyChangeListener {

	private static final int MAX_RESOLUTION = 200;
	private static final int INITIAL_RESOLUTION = 20;
	private static final long serialVersionUID = 1L;

	private IntTextField polynomialDegreeITF_ = new IntTextField(2);
	private IntTextField resolutionITF_ = new IntTextField();
	private PipelineCollection pipelineCollection_;

	SettingsPanel(PipelineCollection pc) {
		super("Settings");

		pipelineCollection_ = pc;
		pipelineCollection_.addPropertyChangeListener(this);

		initTextFields();
		initLayout();
		initAction();
	}

	public int getPP() {
		return polynomialDegreeITF_.getIntValue();
	}

	public void apply() {
		// getCastedModel().getMesh().setP(polynomialDegreeITF_.getIntValue());
	}

	private Model getCastedModel() {
		return ((ModelHolder) pipelineCollection_.getModel()).getModel();
	}

	private LinePlotPipeline getEdgesPipeline() {
		return ((LinePlotPipeline) pipelineCollection_.getPart(HofemPipelineFactory.PL_LINE_PLOT));
	}

	private SolidElementsPipeline getFacesPipeline() {
		return ((SolidElementsPipeline) pipelineCollection_.getPart(HofemPipelineFactory.PL_FACES));
	}

	// private int getP() {
	// Mesh m = getCastedModel().getMesh();
	// if (m.countEdges() > 0) {
	// int p = m.getEdge(0).getP();
	//
	// for (int i = 1; i < m.countEdges(); i++) {
	// if (m.getEdge(i).getP() != p) {
	// return -1;
	// }
	// }
	// return p;
	// }
	// return -1;
	// }

	private void initAction() {

		polynomialDegreeITF_.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// Model m = getCastedModel();

				// m.getMesh().setP(polynomialDegreeITF_.getIntValue());
				solve();
			}
		});
		polynomialDegreeITF_.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				// Model m = getCastedModel();

				// m.getMesh().setP(polynomialDegreeITF_.getIntValue());
				solve();
			}
		});
		resolutionITF_.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				int r = resolutionITF_.getIntValue();
				getFacesPipeline().setResolution(r);
				getEdgesPipeline().setResolution(r);
				pipelineCollection_.render();
			}
		});
		resolutionITF_.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				int r = resolutionITF_.getIntValue();
				getFacesPipeline().setResolution(r);
				getEdgesPipeline().setResolution(r);
				pipelineCollection_.render();
			}
		});
	}

	private void initLayout() {
		JPanel p0 = new JPanel(new BorderLayout(5, 5));
		JPanel p1 = new JPanel(new GridLayout(0, 1, 2, 2));
		JPanel p2 = new JPanel(new GridLayout(0, 1, 2, 2));
		JLabel pL = new JLabel("P. Degree");
		JLabel rL = new JLabel("Resolution");
		String pTTT = "Polynomial Degree";
		String rTTT = "Resolution For Graphical Data";

		pL.setToolTipText(pTTT);
		polynomialDegreeITF_.setToolTipText(pTTT);
		rL.setToolTipText(rTTT);
		resolutionITF_.setToolTipText(rTTT);
		p1.add(pL);
		p2.add(polynomialDegreeITF_);
		p1.add(rL);
		p2.add(resolutionITF_);
		p0.add(p1, BorderLayout.WEST);
		p0.add(p2, BorderLayout.CENTER);
		add(p0);
	}

	private void initTextFields() {
		polynomialDegreeITF_.setRange(1, 30);
		polynomialDegreeITF_.setColumns(2);
		polynomialDegreeITF_.setIncrement(1);
		resolutionITF_.setIncrement(1);
		resolutionITF_.setRange(2, MAX_RESOLUTION);
		resolutionITF_.setIntValue(INITIAL_RESOLUTION);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		Model model = getCastedModel();

		if (model != null) {
			// polynomialDegreeITF_.setIntValue(model.getMesh().getP());
			// resolutionITF_.setIntValue(getLinePlotPipeline().getResolution());
		} else {
			polynomialDegreeITF_.setEnabled(false);
			resolutionITF_.setEnabled(false);
		}
	}

	private void solve() throws Error {
		((Viewer) getTopLevelAncestor()).solve(true, true);
	}

	public void update() {
		// int p = getP();
		//
		// if (p != -1) {
		// polynomialDegreeITF_.setIntValue(p);
		// polynomialDegreeITF_.setEnabled(true);
		// polynomialDegreeITF_.setEditable(true);
		// } else {
		// polynomialDegreeITF_.setIntValue(-1);
		// polynomialDegreeITF_.setEnabled(false);
		// polynomialDegreeITF_.setEditable(false);
		// }
	}
}
